
#include "member_BSource.h"
#include "member_BClass.h"
#include "member_BScript.h"

using namespace BWE;

member_BSource::member_BSource(BSource* source)
{
	boss = source;
	script = 0;
	dirty = false;
}
member_BSource::~member_BSource()
{

}

BString& member_BSource::errorMessage(BExp* exp)
{
	error = true;
	if (message.empty())
	{
		message = new BString();
	}
	BString& text = message;
	text.reset();
	if (exp)
	{
		text << exp->info;
	}
	text << " : error : ";
	return text;
}

bool member_BSource::compile()
{
	error = false;
	stack.clear();
	includes.clear();
	declares.clear();
	functionMap.clear();
	classMap.clear();
	srcnames.clear();
	document.clear();
	if (text.size())
	{
		srcnames += boss->name();
		int pos = 0;
		int line = 0;
		while (pos < text.size())
		{
			BExpHolder exp = compile(text, pos, line);
			if (exp.empty())
				continue;
			checkExp(exp);
			if (exp->syntax == Syntax_Decl)
			{
				for (int i = 0; i < declares.size(); i++)
				{
					BExp* decl = declares[i];
					if (decl->name == exp->name)
					{
						errorMessage(exp) << exp->name << " is already declared.";
						boss->emit(Signal_Message, message);
						script_member(script)->errorMessage(message);
						return false;
					}
				}
				declares.append(exp);
			}
		}
		srcnames -= boss->name();
	}
	if (error)
		return false;
	dirty = false;
	return true;
}

BExp* member_BSource::create(Syntax syntax)
{
	BExp* exp = new BExp();
	exp->syntax = syntax;
	document << exp;
	return exp;
}
BExp* member_BSource::compile(const BString& text, int& pos, int& line)
{
	BExpHolderArray exps;
	BString word;
	while (pos < text.size())
	{
		int begin = nextWord(word, text, pos, line);
		if (word.empty())
			break;
		if (word == "->")
		{
			word = '.';
		}
		if (word == "/*")
		{
			BExp* exp = createBlockNote(text, pos, line);
			return exp;
		}
		if (word == "//")
		{
			BExp* exp = createLineNote(text, pos, line);
			return exp;
		}
		if (word == '#')
		{
			BExp* exp = createMacro(text, pos, line);
			return exp;
		}
		if (word == ',')
		{
			BExp* exp = create(Syntax_Opera);
			exp->name = word;
			exps.append(exp);
			continue;
		}
		if (word == '(')
		{
			BExp* exp = compile(text, pos, line);
			if (exp->name != ')')
			{
				errorMessage(exp) << "chunk is not completed.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
			}
			exp->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
			exp->name = "()";
			exps.append(exp);
			continue;
		}
		if (word == ')')
		{
			BExp* opera = create(Syntax_Opera);
			opera->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
			opera->name = word;
			opera->subs = exps;
			return opera;
		}
		if (word == ';')
		{
			BExp* exp = analyse(exps);
			return exp;
		}
		if (word == '{')
		{
			BExp* exp = analyse(exps);
			BExp* chunk = create(Syntax_Begin);
			chunk->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
			exp->subs.append(chunk);
			while (pos < text.size())
			{
				BExp* sub = compile(text, pos, line);
				if (!sub)
					continue;
				exp->subs.append(sub);
				if (sub->syntax == Syntax_End)
					break;
			}
			BExp* last = exp->subs.last();
			if (last && last->syntax != Syntax_End)
			{
				errorMessage(exp) << "chunk is not completed.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
			}
			return exp;
		}
		if (word == '}')
		{
			BExp* opera = create(Syntax_End);
			opera->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
			return opera;
		}
		if (Syntax syntax = checkSyntax(word))
		{
			BExp* exp = create(syntax);
			exp->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
			exps.append(exp);
			continue;
		}
		if (BExp* exp = createValue(word))
		{
			exp->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
			exps.append(exp);
			continue;
		}
		if (checkOpera(word))
		{
			BExp* exp = create(Syntax_Opera);
			exp->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
			exp->name = word;
			exps.append(exp);
			continue;
		}
		if (checkType(word))
		{
			BExp* exp = create(Syntax_Type);
			exp->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
			exp->type = word;
			exps.append(exp);
			continue;
		}
		BExp* exp = create(Syntax_Name);
		exp->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
		exp->name = word;
		exps.append(exp);
		if (!checkName(word))
		{
			errorMessage(exp) << word << "is invalid name.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
		}
	}
	BExp* exp = analyse(exps);
	return exp;
}
BExp* member_BSource::analyse(BExpHolderArray& exps)
{
	if (exps.empty())
	{
		return 0;
	}
	if (exps.size() == 1)
	{
		return exps[0];
	}

	for (int i = 0; i < exps.size() - 1; i++)
	{
		BExp* exp = exps[i];
		if (exp->syntax == Syntax_Inline)
		{
			exps.remove(i--);
			continue;
		}
		BExp* next = exps(i + 1);
		if (exp->syntax == Syntax_Const)
		{
			if (next && next->syntax == Syntax_Type)
			{
				next->type.prepend("const ");
				exps.remove(i--);
				continue;
			}
		}
		if (exp->syntax == Syntax_Type)
		{
			if (next && next->name == '&')
			{
				exp->type << '&';
				exps.remove(i + 1);
				continue;
			}
		}
	}

	for (int i = 0; i < exps.size(); i++)
	{
		BExp* prev = exps(i - 1);
		BExp* exp = exps[i];
		BExp* next = exps(i + 1);
		if (exp->syntax == Syntax_Else)
		{
			if (i > 0)
			{
				errorMessage(exp) << "else should be first word of expression." << exp->name;
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				return 0;
			}
			if (exps.size() > 1)
			{
				exps.remove(0);
				exp->subs.reset();
				exp->subs.append(analyse(exps));
			}
			return exp;
		}
		if (exp->syntax == Syntax_If || exp->syntax == Syntax_While || exp->syntax == Syntax_Switch)
		{
			if (i > 0)
			{
				errorMessage(exp) << exp->name << " should be first word of expression." << exp->name;
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				return 0;
			}
			BExp* next = exps[i + 1];
			if (next->name != "()")
			{
				errorMessage(next) << exp->name << " has no parameter." << next->name;
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				return 0;
			}
			exp->params = next->subs;
			exp->subs.append(exps, 2, exps.size());
			collateParams(exp->params);
			return exp;
		}
		if (exp->syntax == Syntax_For)
		{
			if (i > 0)
			{
				errorMessage(exp) << exp->name << " should be first word of expression." << exp->name;
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				return 0;
			}
			BExp* next = exps[i + 1];
			exp->params = next->subs;
			exp->subs.append(exps, 2, exps.size());
			collateParams(exp->params);
			return exp;
		}
		if (exp->syntax == Syntax_New)
		{
			if (next->syntax != Syntax_Type)
			{
				errorMessage(exp) << exp->type << " " << exp->name << " invalid operator " << next->name;
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
			}
			exp->type = next->type;
			if (BExp* after = exps(i + 2))
			{
				if (after->name == "()")
				{
					exp->params = after->subs;
					collateParams(exp->params);
				}
				else
				{
					errorMessage(after) << after->type << "should be () for parameters.";
					boss->emit(Signal_Message, message);
					script_member(script)->sourceMessage(message);
				}
			}
			return exp;
		}
		if (exp->syntax == Syntax_Class && next->syntax == Syntax_Name)
		{
			exp->name = next->name;
			next->syntax = Syntax_Type;
			next->type = next->name;
			next->name.clear();
			if (BExp* after = exps(i + 2))
			{
				if (after->syntax != Syntax_Opera || after->name != ':')
				{
					errorMessage(after) << "class declare failed." << after->name;
					boss->emit(Signal_Message, message);
					script_member(script)->sourceMessage(message);
				}
				else
				{
					exp->params.append(exps, i + 3, exps.size());
					collateParams(exp->params);
					for (int i = 0; i < exp->params.size(); i++)
					{
						BExp* param = exp->params[i];
						if (param->subs.empty())
						{
							errorMessage(param) << "class inherit list is invalid.";
							boss->emit(Signal_Message, message);
							script_member(script)->sourceMessage(message);
							continue;
						}
						if (param->subs.size() > 2)
						{
							errorMessage(param) << "class inherit list is too much.";
							boss->emit(Signal_Message, message);
							script_member(script)->sourceMessage(message);
							continue;
						}
						BExp* sub0 = param->subs[0];
						if (sub0->syntax != Syntax_Public && sub0->syntax != Syntax_Protected && sub0->syntax != Syntax_Private)
						{
							errorMessage(sub0) << "class inherit restrict failed.";
							boss->emit(Signal_Message, message);
							script_member(script)->sourceMessage(message);
							continue;
						}
						BExp* sub1 = param->subs[1];
						if (sub1->syntax != Syntax_Type)
						{
							errorMessage(sub1) << sub1->name << "is not class definded.";
							boss->emit(Signal_Message, message);
							script_member(script)->sourceMessage(message);
							continue;
						}
						param->syntax = sub0->syntax;
						param->type = sub1->type;
						if (param->type.empty())
						{
							errorMessage(param->subs[1]) << "class is undeclared.";
							boss->emit(Signal_Message, message);
							script_member(script)->sourceMessage(message);
						}
						param->subs.clear();
					}
				}
			}
			classMap.insert(exp->name);
			return exp;
		}
		if (exp->syntax == Syntax_Name && prev && prev->syntax == Syntax_Type)
		{
			if (next && next->name == "()")
			{
				collateParams(next->subs);
				bool isfunc = true;
				for (int i = 0; i < next->subs.size(); i++)
				{
					if (next->subs[i]->syntax != Syntax_Decl)
					{
						isfunc = false;
						break;
					}
				}
				if (!isfunc)
				{
					errorMessage(exp) << "function define failed, parameters should be decls.";
					boss->emit(Signal_Message, message);
					script_member(script)->sourceMessage(message);
				}
				exp->syntax = Syntax_Function;
				exp->type = prev->type;
				exp->params = next->subs;
				if (BExp* before = exps(i - 2))
				{
					if (before->syntax == Syntax_Virtual)
					{
						exp->name.prepend("[virtual]");
					}
				}
				if (BExp* after = exps(i + 2))
				{
					if (after->syntax == Syntax_Const)
					{
						exp->name.append("[const]");
						exps.remove(i + 2);
					}
				}
				if (exps.size() - i > 2)
				{
					BExpHolderArray& suffixes = exp->value.fill<BExpHolderArray>();
					suffixes.append(exps, i + 2, exps.size() - i - 2);
				}
				return exp;
			}
			BExp* decl = create(Syntax_Decl);
			decl->info = exps[1]->info;
			decl->type = exps[0]->type;
			decl->name = exps[1]->name;
			exps[1]->type = decl->type;
			exps[1]->value = decl;
			int end = findSplit(exps);
			decl->params.append(exps, 2, end - 2);
			if (BExp* param = analyse(decl->params))
			{
				decl->params.reset();
				decl->params.append(param);
			}
			exps.remove(0, end + 1);
			while (exps.size())
			{
				int end = findSplit(exps);
				BExp* rest = create(Syntax_Decl);
				if (exps[0]->syntax == Syntax_Type && exps[1]->syntax == Syntax_Name)
				{
					rest->info = exps[1]->info;
					rest->type = exps[0]->type;
					rest->name = exps[1]->name;
					exps[1]->type = rest->type;
					exps[1]->value = rest;
					rest->params.append(exps, 2, end - 2);
				}
				if (exps[0]->syntax == Syntax_Name)
				{
					rest->info = exps[0]->info;
					rest->type = prev->type;
					rest->name = exps[0]->name;
					exps[0]->type = prev->type;
					exps[0]->value = rest;
					rest->params.append(exps, 1, end - 1);
				}
				if (BExp* param = analyse(rest->params))
				{
					rest->params.reset();
					rest->params.append(param);
				}
				exps.remove(0, end + 1);
				decl->subs.append(rest);
			}
			return decl;
		}
		if (exp->syntax == Syntax_Assign)
		{
			exp->subs.append(exps, i + 1, exps.size() - i - 1);
			exp->subs.append(analyse(exp->subs));
			exps.remove(i + 1, exps.size());
		}
	}

	if (exps.size() > 1 &&
		exps[0]->syntax == Syntax_Type &&
		exps[1]->name == "()")
	{
		if (exps[1]->subs.size())
		{
			errorMessage(exps[1]) << "Constructor can't have parameters.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return 0;
		}
		BExp* exp = exps[0];
		exp->syntax = Syntax_Method;
		exp->name = exp->type;
		exp->params = exps[1]->subs;
		exp->type.clear();
		if (exps.size() > 2)
		{
			BExpHolderArray& suffixes = exp->value.fill<BExpHolderArray>();
			suffixes.append(exps, 2, exps.size() - 2);
			if (exps[2]->syntax == Syntax_Opera && exps[2]->name == ':')
			{
				suffixes.remove(0);
				collateParams(suffixes);
				for (int i = 0; i < suffixes.size(); i++)
				{
					BExpHolder suffix = suffixes[i];
					suffixes[i] = analyse(suffix->subs);
				}
			}
		}
		return exp;
	}

	if (exps.size() > 1 &&
		exps[0]->name == '~' &&
		exps[1]->syntax == Syntax_Type &&
		exps[2]->name == "()")
	{
		BExp* opera = exps[2];
		if (!collateParams(opera->subs))
		{
			return 0;
		}
		BExp* exp = exps[1];
		exp->syntax = Syntax_Method;
		exp->name << exps[0]->name << exp->type;
		exp->params = opera->subs;
		exp->type.clear();
		return exp;
	}

	if (exps.size() >= 3 &&
		exps[0]->syntax == Syntax_Type &&
		exps[1]->name == "::" &&
		exps[2]->syntax == Syntax_Type &&
		exps[3]->name == "()")
	{
		if (exps[0]->type != exps[2]->type)
		{
			errorMessage(exps[2]) << "Constructor declare failed.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
		}
		if (!collateParams(exps[3]->subs))
		{
			return 0;
		}
		BExp* exp = exps[2];
		exp->syntax = Syntax_Method;
		exp->info = exps[0]->info;
		exp->name << exp->type << "::" << exp->type;
		exp->params = exps[3]->subs;
		exp->type.clear();
		if (exps.size() > 4)
		{
			BExpHolderArray& suffixes = exp->value.fill<BExpHolderArray>();
			suffixes.append(exps, 4, exps.size() - 4);
			if (exps[4]->syntax == Syntax_Opera && exps[4]->name == ':')
			{
				suffixes.remove(0);
				collateParams(suffixes);
				for (int i = 0; i < suffixes.size(); i++)
				{
					BExpHolder suffix = suffixes[i];
					suffixes[i] = analyse(suffix->subs);
				}
			}
		}
		return exp;
	}

	if (exps.size() >= 5 &&
		exps[0]->syntax == Syntax_Type &&
		exps[1]->name == "::" &&
		exps[2]->name == '~' &&
		exps[3]->syntax == Syntax_Type &&
		exps[4]->name == "()")
	{
		if (exps[0]->type != exps[3]->type)
		{
			errorMessage(exps[2]) << "Constructor declare failed.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
		}
		if (exps[4]->subs.size())
		{
			errorMessage(exps[4]) << "destructor can't have parameters.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
		}
		BExp* exp = exps[3];
		exp->syntax = Syntax_Method;
		exp->info = exps[0]->info;
		exp->name << exp->type << "::~" << exp->type;
		exp->type.clear();
		if (exps.size() > 5)
		{
			BExpHolderArray& suffixes = exp->value.fill<BExpHolderArray>();
			suffixes.append(exps, 5, exps.size() - 5);
		}
		return exp;
	}

	if (exps.size() >= 5 &&
		exps[0]->syntax == Syntax_Type &&
		exps[1]->syntax == Syntax_Type &&
		exps[2]->name == "::" &&
		exps[3]->syntax == Syntax_Name &&
		exps[4]->name == "()")
	{
		if (!collateParams(exps[4]->subs))
		{
			return 0;
		}
		BExp* exp = exps[3];
		exp->syntax = Syntax_Method;
		exp->info = exps[0]->info;
		exp->type = exps[0]->type;
		exp->name.prepend("::");
		exp->name.prepend(exps[1]->type);
		exp->params = exps[4]->subs;
		if (exps.size() > 5)
		{
			BExpHolderArray& suffixes = exp->value.fill<BExpHolderArray>();
			suffixes.append(exps, 5, exps.size() - 5);
		}
		return exp;
	}

	if (exps[0]->syntax == Syntax_Return)
	{
		BExp* exp = exps[0];
		exp->params.append(exps, 1, exps.size() - 1);
		collateParams(exp->params);
		return exp;
	}
	if (exps.size() == 1)
	{
		return exps[0];
	}
	BExp* exp = create(Syntax_None);
	exp->info = exps[0]->info;
	exp->subs = exps;
	return exp;
}
BExp* member_BSource::createMacro(const BString& text, int& pos, int& line)
{
	BString word;
	int begin = nextWord(word, text, pos, line);
	if (word == "include")
	{
		BExp* include = create(Syntax_Include);
		include->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
		begin = nextWord(word, text, pos, line);
		pos = text.find('\n', pos);
		text.substr(word, begin, pos);
		word.trimmed();
		BExp* param = create(Syntax_File);
		param->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
		param->name = word;
		include->params.append(param);
		if (word.beginWith('<') && word.endWith('>'))
		{
			word.remove('<');
			word.remove('>');
			include->name = word;
			includes.append(include);
			if (!script_member(script)->include(word))
			{
				errorMessage(param) << "include header failed " << word;
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
			}
			return include;
		}
		if (!word.beginWith('\"') || !word.endWith('\"'))
		{
			errorMessage(param) << "include file failed " << word;
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return include;
		}
		word.remove('\"');
		word.remove('\"');
		if (srcnames.contain(word))
		{
			errorMessage(param) << "loop include file failed " << word;
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return include;
		}
		BSource* source = script->source(word);
		if (!source)
		{
			errorMessage(param) << "include file failed " << word;
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return include;
		}
		if (source_member(source)->text.size())
		{
			srcnames.append(word);
			int pos = 0;
			int line = 0;
			while (pos < source_member(source)->text.size())
			{
				BExpHolder exp = compile(source_member(source)->text, pos, line);
				if (exp.empty())
					continue;
				if (exp->syntax == Syntax_Decl)
				{
					for (int i = 0; i < declares.size(); i++)
					{
						BExp* decl = declares[i];
						if (decl->name == exp->name)
						{
							errorMessage(exp) << exp->name << " is already declared.";
							boss->emit(Signal_Message, message);
							script_member(script)->sourceMessage(message);
						}
					}
					declares.append(exp);
				}
				include->subs.append(exp);
			}
			srcnames.remove(srcnames.size() - 1);
		}
		return include;
	}
	BExp* none = create(Syntax_None);
	errorMessage(none) << word << "is invalid macro.";
	boss->emit(Signal_Message, message);
	script_member(script)->sourceMessage(message);
	return none;
}
BExp* member_BSource::createLineNote(const BString& text, int& pos, int& line)
{
	BExp* exp = create(Syntax_Note);
	int begin = pos - 2;
	while (pos < text.size())
	{
		if (text[pos++] == '\n')
		{
			line++;
			break;
		}
	}
	exp->info << srcnames.last() << ':' << line << '(' << begin << ", " << pos << ')';
	return exp;
}
BExp* member_BSource::createBlockNote(const BString& text, int& pos, int& line)
{
	BExp* exp = create(Syntax_Note);
	int begin = pos - 2;
	exp->info << srcnames.last() << ':' << line;
	while (pos < text.size())
	{
		if (text[pos] == '\n')
		{
			line++;
			pos++;
			continue;
		}
		if (text[pos++] == '*' && text[pos++] == '/')
		{
			break;
		}
	}
	exp->info << '(' << begin << ", " << pos << ')';
	exp->value = line;
	return exp;
}
BExp* member_BSource::createValue(BString& word)
{
	if (word[0] == '\"')
	{
		BExp* exp = create(Syntax_Value);
		word.remove(0);
		if (word.endWith('\"'))
		{
			word -= '\"';
		}
		else
		{
			errorMessage(exp) << "string is not finished.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
		}
		exp->type = "string";
		exp->value = word;
		return exp;
	}
	if (word == "true")
	{
		BExp* exp = create(Syntax_Value);
		exp->type = "bool";
		exp->value = true;
		return exp;
	}
	if (word == "false")
	{
		BExp* exp = create(Syntax_Value);
		exp->type = "bool";
		exp->value = false;
		return exp;
	}
	if (word.isNumber())
	{
		BExp* exp = create(Syntax_Value);
		if (word.contain('.'))
		{
			if (word.endWith('f'))
			{
				float v = word.toFloat();
				exp->type = "float";
				exp->value = v;
			}
			else
			{
				double v = word.toDouble();
				exp->type = "double";
				exp->value = v;
			}
		}
		else
		{
			if (word.endWith("ul"))
			{
				unsigned long long v = word.toLong();
				exp->type = "ulong";
				exp->value = v;
			}
			else if (word.endWith('l'))
			{
				long long v = word.toLong();
				exp->type = "long";
				exp->value = v;
			}
			else
			{
				int v = word.toInt();
				exp->type = "int";
				exp->value = v;
			}
		}
		return exp;
	}
	return 0;
}
bool member_BSource::collateParams(BExpHolderArray& exps)
{
	if (exps.size() < 2)
		return true;
	int begin = 0;
	for (int i = 0; i < exps.size(); i++)
	{
		BExp* exp = exps[i];
		if (exp->syntax == Syntax_Opera && exp->name == ',')
		{
			int count = i - begin;
			if (count > 1)
			{
				exp->subs.append(exps, begin, count);
				BExp* param = analyse(exp->subs);
				exps.remove(begin, count);
				exps[begin] = param;
				exp->subs.clear();
			}
			else
			{
				exps.remove(i);
			}
			i = begin++;
		}
	}
	if (begin > 0)
	{
		int count = exps.size() - begin;
		if (count > 1)
		{
			BExpHolderArray subs(exps, begin, count);
			BExp* exp = analyse(subs);
			exps.remove(begin, count);
			exps.append(exp);
		}
	}
	else
	{
		exps.reset();
		BExp* param = analyse(exps);
		exps.append(param);
	}
	return true;
}

bool member_BSource::checkExp(BExp* exp)
{
	switch (exp->syntax)
	{
	case Syntax_None:
	{
		if (exp->type.empty())
		{
			exp->type = checkFormula(exp->subs);
		}
		return true;
	}
	case Syntax_Include:
	{
		for (int i = 0; i < exp->subs.size(); i++)
		{
			checkExp(exp->subs[i]);
		}
		return true;
	}
	case Syntax_Begin:
		return true;
	case Syntax_End:
		return true;
	case Syntax_Value:
		return true;
	case Syntax_Decl:
	{
		if (exp->type.endWith('&'))
		{
			if (exp->params.size() != 1)
			{
				errorMessage(exp) << "reference should init with single parameter.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				return false;
			}
			BExp* param = exp->params.first();
			checkExp(param);
			if (exp->type == param->type)
				return true;
			if (exp->type.beginWith("const "))
			{
				BString type;
				exp->type.word(type, 6);
				if (type == param->type)
					return true;
				type << '&';
				if (type == param->type)
					return true;
			}
			return false;
		}
		BClass* cls = findClass(exp->type);
		if (!cls)
		{
			errorMessage(exp) << "class " << exp->type << " is not declared.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		BVariant& var = stack.push();
		var.setType(exp->type);
		var.setName(exp->name);
		var.setValue(cls);
		if (exp->params.size() > 1)
		{
			errorMessage(exp) << "too many expressions after decl.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
		}
		if (BExp* param = exp->params.first())
		{
			checkExp(param);
			if (param->syntax != Syntax_Assign)
			{
				errorMessage(exp) << "decl should be followed by assign expression.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
			}
			else
			{
				if (exp->type != param->type)
				{
					errorMessage(exp) << "invalid operation : assign " << param->type << " to " << exp->type;
					boss->emit(Signal_Message, message);
					script_member(script)->sourceMessage(message);
				}
			}
		}
		for (int i = 0; i < exp->subs.size(); i++)
		{
			checkExp(exp->subs[i]);
		}
		return true;
	}
	case Syntax_Name:
	{
		if (exp->subs.empty())
		{
			if (BVariant* ptr = checkVariant(exp->name))
			{
				exp->type = ptr->type();
				return true;
			}
			if (BClass* self = checkSelf())
			{
				if (BVariant* ptr = self->variant(exp->name))
				{
					exp->syntax = Syntax_Self;
					exp->type = ptr->type();
					return true;
				}
			}
			errorMessage(exp) << exp->name << " is not declared.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		if (BVariant* ptr = checkVariant(exp->subs))
		{
			exp->type = ptr->type();
			return true;
		}
		if (BClass* self = checkSelf())
		{
			if (BVariant* ptr = self->variant(exp->subs.first()->name))
			{
				for (int i = 1; i < exp->subs.size(); i++)
				{
					BExp* sub = exp->subs[i];
					BClass* cls = findClass(ptr->type());
					if (!cls)
						break;
					ptr = cls->variant(sub->name);
					if (!ptr)
						break;
					sub->type = ptr->type();
				}
				if (ptr)
				{
					exp->syntax = Syntax_Self;
					exp->type = ptr->type();
					return true;
				}
			}
		}
		errorMessage(exp) << exp->name << " is not declared.";
		boss->emit(Signal_Message, message);
		script_member(script)->sourceMessage(message);
		return false;
	}
	case Syntax_Self:
	{
		BClass* self = 0;
		for (int i = stack.size() - 1; i >= 0; i--)
		{
			BVariant& var = stack[i];
			if (CallInfo* cinfo = var.value())
			{
				self = cinfo->self;
				exp->type = var.type();
				break;
			}
		}
		if (!self)
		{
			errorMessage(exp) << "self is unfound.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		if (exp->subs.empty())
		{
			BVariant* ptr = self->variant(exp->name);
			if (!ptr)
			{
				errorMessage(exp) << exp->name << " is unfound.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				return false;
			}
			exp->type = ptr->type();
			return true;
		}
		BVariant* ptr = self->variant(exp->subs.first()->name);
		if (!ptr)
		{
			errorMessage(exp->subs.first()) << exp->subs.first()->name << " is unfound.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		for (int i = 1; i < exp->subs.size(); i++)
		{
			BExp* sub = exp->subs[i];
			if (BClass* cls = findClass(ptr->type()))
			{
				ptr = cls->variant(sub->name);
				if (!ptr)
				{
					errorMessage(exp) << exp->name << " is not declared.";
					boss->emit(Signal_Message, message);
					script_member(script)->sourceMessage(message);
					break;
				}
				exp->type = ptr->type();
			}
			else
			{
				errorMessage(exp) << ptr->type() << "::" << exp->name << " is not declared.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				return false;
			}
		}
		exp->type = ptr->type();
		return true;
	}
	case Syntax_Assign:
	{
		exp->type = checkFormula(exp->subs);
		return true;
	}
	case Syntax_Opera:
	{
		for (int i = 0; i < exp->params.size(); i++)
		{
			checkExp(exp->params[i]);
		}
		exp->name = this->funcName(exp);
		BClass* cls = findClass(exp->type);
		if (!cls)
		{
			errorMessage(exp) << "class " << exp->type << " is not declared.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		if (Method* method = class_member(cls)->methodMap(exp->name))
		{
			exp->name.prepend("::");
			exp->name.prepend(exp->type);
			exp->type = method->type;
			return true;
		}
		errorMessage(exp) << "operator " << exp->type << "::" << exp->name << " is not declared.";
		boss->emit(Signal_Message, message);
		script_member(script)->sourceMessage(message);
		return false;
	}
	case Syntax_Call:
	{
		BVariant* var = exp->value;
		if (!var && exp->subs.size())
		{
			var = checkVariant(exp->subs);
			if (!var)
				return false;
		}
		for (int i = 0; i < exp->params.size(); i++)
		{
			checkExp(exp->params[i]);
		}
		if (var)
		{
			if (BClass* cls = *var)
			{
				BString methodName = this->funcName(exp);
				if (Method* method = class_member(cls)->methodMap(methodName))
				{
					exp->name.reset();
					exp->name << var->type() << "::" << methodName;
					exp->type = method->type;
					exp->value = method;
					return true;
				}
				for (auto it = class_member(cls)->methodMap.begin(); it.valid(); ++it)
				{
					const BString& name = it.key();
					Method* method = it.value();
					if (name.beginWith(exp->name) && method->params.size() == exp->params.size())
					{
						if (matchMethod(exp, method))
						{
							exp->name = funcName(exp);
							exp->name.prepend("::");
							exp->name.prepend(var->type());
							exp->value = method;
							return true;
						}
					}
				}
				for (int i = 0; i < class_member(cls)->inherits.size(); i++)
				{
					BClass* up = class_member(cls)->inherits[i]->value;
					for (auto it = class_member(up)->methodMap.begin(); it.valid(); ++it)
					{
						const BString& name = it.key();
						Method* method = it.value();
						if (name.beginWith(exp->name) && method->params.size() == exp->params.size())
						{
							if (matchMethod(exp, method))
							{
								exp->name = funcName(exp);
								exp->name.prepend("::");
								exp->name.prepend(class_member(cls)->inherits[i]->type);
								exp->value = method;
								return true;
							}
						}
					}
				}
			}
			errorMessage(exp) << "method " << var->type() << "::" << exp->name << " is not declared.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		BString funcName = this->funcName(exp);
		if (Function* function = findFunction(funcName))
		{
			exp->name = funcName;
			exp->type = function->type;
			exp->value = function;
			return true;
		}
		for (auto it = script_member(script)->presets.functionMap.begin(); it.valid(); ++it)
		{
			const BString& name = it.key();
			Function* function = it.value();
			if (name.beginWith(exp->name) && function->params.size() == exp->params.size())
			{
				if (matchFunction(exp, function))
					return true;
			}
		}
		for (auto it = functionMap.begin(); it.valid(); ++it)
		{
			const BString& name = it.key();
			Function* function = it.value();
			if (name.beginWith(exp->name) && function->params.size() == exp->params.size())
			{
				if (matchFunction(exp, function))
					return true;
			}
		}
		errorMessage(exp) << "function " << funcName << " is not declared.";
		boss->emit(Signal_Message, message);
		script_member(script)->sourceMessage(message);
		return false;
	}
	case Syntax_If:
	{
		if (exp->params.empty())
		{
			errorMessage(exp) << "if need single bool param. if(bool)";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		if (exp->params.size() > 1)
		{
			errorMessage(exp) << "if has to many params.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		int top = stack.size();
		if (BExp* param = exp->params[0])
		{
			checkExp(param);
			if (param->type != "bool")
			{
				BExpHolder decl = new BExp(Syntax_Decl);
				decl->info = param->info;
				decl->type = "bool";
				decl->params = exp->params;
				if (!checkExp(decl))
				{
					errorMessage(param) << "if param should be bool, failed to convert " << param->type << " to bool.";
					boss->emit(Signal_Message, message);
					script_member(script)->sourceMessage(message);
					return false;
				}
				exp->params[0] = decl;
			}
		}
		for (int i = 0; i < exp->subs.size(); i++)
		{
			checkExp(exp->subs[i]);
		}
		stack.back(top);
		return true;
	}
	case Syntax_Else:
	{
		int top = stack.size();
		for (int i = 0; i < exp->subs.size(); i++)
		{
			checkExp(exp->subs[i]);
		}
		stack.back(top);
		return !error;
	}
	case Syntax_While:
	{
		if (exp->params.empty())
		{
			errorMessage(exp) << "while need single bool param : while(bool).";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		if (BExp* second = exp->params(1))
		{
			errorMessage(second) << "while has to many params.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		int top = stack.size();
		if (BExp* param = exp->params[0])
		{
			checkExp(param);
			if (param->type != "bool")
			{
				BExpHolder decl = new BExp(Syntax_Decl);
				decl->info = param->info;
				decl->type = "bool";
				decl->params = exp->params;
				if (!checkExp(decl))
				{
					errorMessage(param) << "if param should be bool, failed to convert " << param->type << " to bool.";
					boss->emit(Signal_Message, message);
					script_member(script)->sourceMessage(message);
					return false;
				}
				exp->params[0] = decl;
			}
		}
		stack.push(Syntax_While);
		for (int i = 0; i < exp->subs.size(); i++)
		{
			checkExp(exp->subs[i]);
		}
		stack.back(top);
		return true;
	}
	case Syntax_For:
	{
		if (exp->params.size() != 3)
		{
			errorMessage(exp) << "for need three params : for(any;bool;any).";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		int top = stack.size();
		for (int i = 0; i < exp->params.size(); i++)
		{
			checkExp(exp->params[i]);
		}
		BExp* second = exp->params[1];
		if (second->type != "bool")
		{
			BExpHolder decl = new BExp(Syntax_Decl);
			decl->info = second->info;
			decl->type = "bool";
			decl->params = exp->params;
			if (!checkExp(decl))
			{
				errorMessage(second) << "for second param should be bool, failed to convert " << second->type << " to bool.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				return false;
			}
			exp->params[1] = decl;
		}
		stack.push(Syntax_For);
		for (int i = 0; i < exp->subs.size(); i++)
		{
			checkExp(exp->subs[i]);
		}
		stack.back(top);
		return true;
	}
	case Syntax_Return:
	{
		BVariant* loop = 0;
		for (int i = stack.size() - 1; i >= 0; i--)
		{
			BVariant& var = stack[i];
			if (var.value() == Syntax_Function)
				break;
		}
		for (int i = 0; i < exp->params.size(); i++)
		{
			checkExp(exp->params[i]);
		}
		CallInfo* cinfo = 0;
		for (int i = stack.size() - 1; i >= 0; i--)
		{
			BVariant& var = stack[i];
			cinfo = var.value();
			if (cinfo)
				break;
		}
		if (cinfo == 0)
		{
			errorMessage(exp) << "return used out of function.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		if (cinfo->type.size() && exp->params.empty())
		{
			errorMessage(exp) << "return value of type " << cinfo->type;
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		if (cinfo->type.empty() && exp->params.size())
		{
			errorMessage(exp) << "should return nothing here." << cinfo->type;
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		if (BExp* param = exp->params.first())
		{
			if (cinfo->type != param->type)
			{
				BExpHolder decl = new BExp(Syntax_Decl);
				decl->type = cinfo->type;
				decl->params.reset();
				decl->params.append(param);
				if (checkExp(decl))
				{
					exp->params.prepend(decl);
					return true;
				}
				errorMessage(param) << "function return type don't match.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				return false;
			}
		}
		return true;
	}
	case Syntax_Break:
	case Syntax_Continue:
	{
		BVariant* loop = 0;
		for (int i = stack.size() - 1; i >= 0; i--)
		{
			BVariant& var = stack[i];
			if (var.value() == Syntax_While || var.value() == Syntax_For)
			{
				loop = &var;
				break;
			}
			if (var.value() == Syntax_Function)
				break;
		}
		if (!loop)
		{
			errorMessage(exp) << "continue is out of loop syntax.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		return true;
	}
	case Syntax_Class:
	{
		BClass* cls = classMap[exp->name];
		if (exp->subs.empty())
		{
			return true;
		}
		if (cls)
		{
			errorMessage(exp) << "class " << exp->name << "is redeclared.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		cls = new BClass();
		class_member(cls)->inherits = exp->params;
		for (int i = 0; i < exp->params.size(); i++)
		{
			BExp* param = exp->params[i];
			param->value = findClass(param->type);
		}
		for (int i = 0; i < exp->subs.size(); i++)
		{
			BExp* sub = exp->subs[i];
			if (sub->syntax == Syntax_Begin && i == 0)
				continue;
			if (sub->syntax == Syntax_End && i == exp->subs.size() - 1)
				continue;
			if (sub->syntax == Syntax_Decl)
			{
				BVariant& var = class_member(cls)->variantMap[sub->name];
				var.setType(sub->type);
				var.setName(sub->name);
				var.setValue(sub);
				int top = stack.size();
				checkExp(sub);
				stack.back(top);
				BExp* self = new BExp(Syntax_Self);
				self->name = sub->name;
				sub->subs.prepend(self);
				continue;
			}
			if (sub->syntax == Syntax_Function || sub->syntax == Syntax_Method)
			{
				Method* method = new Method();
				method->type = sub->type;
				sub->syntax = Syntax_Method;
				if (sub->subs.size())
				{
					method->value = sub;
				}
				if (sub->name.beginWith("[virtual]"))
				{
					method->virt = true;
					sub->name.remove("[virtual]");
				}
				if (sub->name.endWith("[const]"))
				{
					method->cnst = true;
					sub->name -= "[const]";
				}
				class_member(cls)->methodMap[funcName(sub)] = method;
				for (int i = 0; i < sub->params.size(); i++)
				{
					BExp* param = sub->params[i];
					BVariant& var = method->params.append();
					var.setType(param->type);
					var.setName(param->name);
				}
				if (BExpHolderArray* suffixes = sub->value)
				{
					if (suffixes->size() == 2 && suffixes->first()->syntax == Syntax_Assign && (*suffixes)[1]->value == 0)
					{
						if (method->virt)
						{
							method->value = 0;
						}
						else
						{
							errorMessage(suffixes->first()) << "method is not virtual, can't assign 0.";
							boss->emit(Signal_Message, message);
							script_member(script)->sourceMessage(message);
						}
					}
					else
					{
						errorMessage(suffixes->first()) << "method suffix is invalid.";
						boss->emit(Signal_Message, message);
						script_member(script)->sourceMessage(message);
					}
				}
				continue;
			}
			errorMessage(sub) << "invalid expression in class declaration.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
		}
		classMap[exp->name] = cls;
		int top = stack.size();
		for (int i = 0; i < exp->subs.size(); i++)
		{
			BExp* sub = exp->subs[i];
			if (sub->syntax == Syntax_Method && sub->subs.size())
			{
				sub->name.prepend("::");
				sub->name.prepend(exp->name);
				checkExp(sub);
			}
		}
		stack.back(top);
		return true;
	}
	case Syntax_Method:
	{
		BString type;
		int split = exp->name.word(type, 0);
		exp->name.remove(0, split + 2);
		bool isConst = false;
		if (exp->name.endWith("[const]"))
		{
			isConst = true;
			exp->name -= "[const]";
		}
		bool isConstructor = type == exp->name;
		BClass* cls = findClass(type);
		if (!cls)
		{
			errorMessage(exp) << "class " << type << " is not declared.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		exp->name = this->funcName(exp);
		Method* method = class_member(cls)->methodMap(exp->name);
		if (!method)
		{
			errorMessage(exp) << exp->type << ' ' << exp->name << " is not declared.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return false;
		}
		if (method->value != exp)
		{
			if (method->cnst != isConst)
			{
				errorMessage(exp) << "method " << exp->type << "::" << exp->name << " is const.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				return false;
			}
			if (method->value.valid() && exp->subs.size())
			{
				errorMessage(exp) << "method " << exp->type << ' ' << exp->name << " is redeclared.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				return false;
			}
			method->value = exp;
		}

		int top = stack.size();
		CallInfo* cinfo = new CallInfo;
		cinfo->top = top;
		cinfo->type = exp->type;
		cinfo->self = cls;
		BVariant& res = stack.push(cinfo);
		res.setType(type);
		res.setName(exp->name);
		res.setValue(cinfo);
		for (int i = 0; i < exp->params.size(); i++)
		{
			BExp* param = exp->params[i];
			BVariant& var = stack.push();
			var.setType(param->type);
			var.setName(param->name);
			var.setValue(findClass(param->type));
			if (var.value().empty())
			{
				errorMessage(param) << "class " << param->type << " is undeclared.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				continue;
			}
		}
		for (int i = 0; i < exp->subs.size(); i++)
		{
			checkExp(exp->subs[i]);
		}
		for (int i = 0; i < exp->subs.size(); i++)
		{
			BExp* sub = exp->subs[i];
			if (sub->syntax == Syntax_If)
			{
				BExp* next = exp->subs(i + 1);
				if (next && next->syntax == Syntax_Else)
				{
					sub->params.append(next);
					exp->subs.remove(i + 1);
				}
				continue;
			}
			if (sub->syntax == Syntax_Else)
			{
				errorMessage(sub) << "else should follow if .";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				continue;
			}
		}
		stack.back(top);
		if (isConstructor)
		{
			BMap<BString, BExpHolder> initMap;
			if (BExpHolderArray* suffixes = exp->value)
			{
				if (suffixes->first()->syntax == Syntax_Const)
				{
					errorMessage(suffixes->first()) << "Constructor can not be const.";
					boss->emit(Signal_Message, message);
					script_member(script)->sourceMessage(message);
				}
				for (int i = 0; i < suffixes->size(); i++)
				{
					BExp* suffix = suffixes->at(i);
					if (!checkExp(suffix))
						continue;
					if (suffix->syntax != Syntax_Call)
					{
						errorMessage(suffix) << "expression is invalid here.";
						boss->emit(Signal_Message, message);
						script_member(script)->sourceMessage(message);
						continue;
					}
					if (!class_member(cls)->checkInherit(suffix->name))
					{
						errorMessage(suffix) << type << " is not inherit from " << suffix->name;
						boss->emit(Signal_Message, message);
						script_member(script)->sourceMessage(message);
						continue;
					}
					if (this->findClass(suffix->name))
					{
						initMap.insert(suffix->name, suffix);
					}
				}
			}
			for (int i = 0; i < class_member(cls)->inherits.size(); i++)
			{
				const BString& type = class_member(cls)->inherits[i]->type;
				if (initMap.contain(type))
					continue;
				BClass* up = class_member(cls)->inherits[i]->value;
				if (!up)
					continue;
				BExp* call = new BExp(Syntax_Call);
				call->name << type << "::" << type << "()";
				initMap.insert(type, call);
			}
			for (auto it = class_member(cls)->variantMap.begin(); it.valid(); ++it)
			{
				if (BExp* decl = it->value())
				{
					exp->subs.prepend(decl->subs);
				}
			}
			for (int i = 0; i < initMap.size(); i++)
			{
				BExp* call = *initMap.seek(i);
				call->subs.append(new BExp(Syntax_Self));
				exp->subs.prepend(call);
			}
		}
		else
		{
			if (BExpHolderArray* suffixes = exp->value)
			{
				if (suffixes->first()->syntax == Syntax_Const)
				{
					method->cnst = true;
				}
			}
		}
		return !error;
	}
	case Syntax_Function:
	{
		exp->name = this->funcName(exp);
		Function* func = this->functionMap(exp->name);
		if (!func)
		{
			func = new Function();
			func->sfunc = exp;
			func->type = exp->type;
			for (int i = 0; i < exp->params.size(); i++)
			{
				BExp* param = exp->params[i];
				BVariant& var = func->params.append();
				var.setType(param->type);
				var.setName(param->name);
			}
			this->functionMap[exp->name] = func;
		}
		int top = stack.size();
		CallInfo* cinfo = new CallInfo;
		cinfo->top = top;
		cinfo->type = exp->type;
		BVariant& res = stack.push();
		res.setType(exp->type);
		res.setName(exp->name);
		res.setValue(cinfo);
		for (int i = 0; i < exp->params.size(); i++)
		{
			BExp* param = exp->params[i];
			BVariant& var = stack.push();
			var.setType(param->type);
			var.setName(param->name);
			var.setValue(findClass(param->type));
			if (var.value().empty())
			{
				errorMessage(param) << "class " << param->type << " is undeclared.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				continue;
			}
		}
		for (int i = 0; i < exp->subs.size(); i++)
		{
			checkExp(exp->subs[i]);
		}
		for (int i = 0; i < exp->subs.size(); i++)
		{
			BExp* sub = exp->subs[i];
			if (sub->syntax == Syntax_If)
			{
				BExp* next = exp->subs(i + 1);
				if (next && next->syntax == Syntax_Else)
				{
					sub->params.append(next);
					exp->subs.remove(i + 1);
				}
				continue;
			}
			if (sub->syntax == Syntax_Else)
			{
				errorMessage(sub) << "else should follow if .";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				continue;
			}
		}
		stack.back(top);
		return !error;
	}
	default:
		return false;
	}
	return !error;
}
bool member_BSource::checkType(const BString& text)
{
	if (text == "void")
		return true;
	if (text == "bool")
		return true;
	if (text == "char")
		return true;
	if (text == "byte")
		return true;
	if (text == "short")
		return true;
	if (text == "ushort")
		return true;
	if (text == "int")
		return true;
	if (text == "uint")
		return true;
	if (text == "long")
		return true;
	if (text == "ulong")
		return true;
	if (text == "float")
		return true;
	if (text == "double")
		return true;
	if (text == "string")
		return true;
	if (classMap.contain(text))
		return true;
	if (script_member(script)->presets.classMap(text))
		return true;
	return false;
}
bool member_BSource::checkOpera(const BString& word)
{
	if (word == '.')
		return true;
	else if (word == '+')
		return true;
	else if (word == '-')
		return true;
	else if (word == '*')
		return true;
	else if (word == '/')
		return true;
	else if (word == '<')
		return true;
	else if (word == '>')
		return true;
	else if (word == '!')
		return true;
	else if (word == "==")
		return true;
	else if (word == "!=")
		return true;
	else if (word == "+=")
		return true;
	else if (word == "-=")
		return true;
	else if (word == "*=")
		return true;
	else if (word == "/=")
		return true;
	else if (word == "<=")
		return true;
	else if (word == ">=")
		return true;
	else if (word == "++")
		return true;
	else if (word == "--")
		return true;
	else if (word == '~')
		return true;
	else if (word == '&')
		return true;
	else if (word == ':')
		return true;
	else if (word == "::")
		return true;
	return false;
}
bool member_BSource::checkName(const BString& name)
{
	if (name.empty())
		return false;
	char c = name[0];
	if (c == '_')
		return true;
	if (isalnum(c))
		return true;
	return false;
}
Syntax member_BSource::checkSyntax(const BString& text)
{
	if (text == '=')
		return Syntax_Assign;
	if (text == "self" || text == "this")
		return Syntax_Self;
	if (text == "new")
		return Syntax_New;
	if (text == "if")
		return Syntax_If;
	if (text == "else")
		return Syntax_Else;
	if (text == "elif")
		return Syntax_Else;
	if (text == "for")
		return Syntax_For;
	if (text == "while")
		return Syntax_While;
	if (text == "switch")
		return Syntax_Switch;
	if (text == "case")
		return Syntax_Case;
	if (text == "default")
		return Syntax_Default;
	if (text == "continue")
		return Syntax_Continue;
	if (text == "break")
		return Syntax_Break;
	if (text == "return")
		return Syntax_Return;
	if (text == "const")
		return Syntax_Const;
	if (text == "virtual")
		return Syntax_Virtual;
	if (text == "class")
		return Syntax_Class;
	if (text == "public")
		return Syntax_Public;
	if (text == "protected")
		return Syntax_Protected;
	if (text == "private")
		return Syntax_Private;
	return Syntax_None;
}
BString member_BSource::checkFormula(BExpHolderArray& exps)
{
	BString type;
	if (exps.empty())
		return type;
	for (int i = 0; i < exps.size() - 1; i++)
	{
		BExp* sub = exps[i];
		if (sub->syntax == Syntax_Name || sub->syntax == Syntax_Self)
		{
			int end = i;
			BExp* last = 0;
			while (++end < exps.size())
			{
				last = exps(end);
				if (last->name == '.')
					continue;
				if (last->syntax == Syntax_Name)
					continue;
				if (last->syntax == Syntax_Self)
				{
					errorMessage(last) << last->name << " should be first word of location.";
					boss->emit(Signal_Message, message);
					script_member(script)->sourceMessage(message);
					return false;
				}
				break;
			}
			if (sub->syntax == Syntax_Self)
			{
				if (last->name == "()")
				{
					sub->subs.append(exps, i + 1, end - i - 2);
					checkPath(sub->subs);
					BExp* call = exps[end - 1];
					call->syntax = Syntax_Call;
					call->params = last->subs;
					call->subs.reset();
					call->subs.append(sub);
					exps.remove(end);
					exps.remove(i, end - i - 1);
					collateParams(call->params);
				}
				else if (end - i > 1)
				{
					sub->subs.append(exps, i + 1, end - i - 1);
					checkPath(sub->subs);
					exps.remove(i + 1, end - 1);
				}
				continue;
			}
			if (last->name == "()")
			{
				BExp* call = exps[end - 1];
				call->syntax = Syntax_Call;
				call->params = last->subs;
				call->subs.append(exps, i, end - i - 1);
				exps.remove(end);
				exps.remove(i, end - i - 1);
				collateParams(call->params);
				checkPath(call->subs);
			}
			else if (end - i > 1)
			{
				BExp* name = new BExp();
				name->syntax = Syntax_Name;
				name->subs.append(exps, i, end - i);
				exps.remove(i, end);
				exps.insert(i, name);
				checkPath(name->subs);
			}
		}
	}
	for (int i = 0; i < exps.size(); i++)
	{
		BExp* sub = exps(i);
		if (sub->syntax == Syntax_Opera)
		{
			if (BExp* next = exps(i + 1))
			{
				sub->params.append(next);
				exps.remove(next);
			}
			sub->type = type;
			if (!checkExp(sub))
				return false;
			type = sub->type;
		}
		else
		{
			if (!checkExp(sub))
				return false;
			type = sub->type;
		}
	}
	return type;
}
BClass* member_BSource::checkSelf()
{
	for (int i = stack.size() - 1; i >= 0; i--)
	{
		BVariant& var = stack[i];
		if (CallInfo* cinfo = var.value())
			return cinfo->self;
	}
	return 0;
}
BVariant* member_BSource::checkVariant(const BString& name)
{
	for (int i = stack.size() - 1; i >= 0; i--)
	{
		BVariant& var = stack[i];
		if (var.name() == name)
			return &var;
	}
	return 0;
}
BVariant* member_BSource::checkVariant(const BExpHolderArray& exps)
{
	if (exps.empty())
		return 0;
	BExp* first = exps.first();
	BVariant* ptr = checkVariant(first->name);
	if (!ptr)
	{
		errorMessage(first) << first->name << " is not declared.";
		boss->emit(Signal_Message, message);
		script_member(script)->sourceMessage(message);
		return ptr;
	}
	first->type = ptr->type();
	for (int i = 1; i < exps.size(); i++)
	{
		BExp* exp = exps[i];
		if (BClass* cls = findClass(ptr->type()))
		{
			ptr = cls->variant(exp->name);
			if (!ptr)
			{
				errorMessage(exp) << exp->name << " is not declared.";
				boss->emit(Signal_Message, message);
				script_member(script)->sourceMessage(message);
				break;
			}
			exp->type = ptr->type();
		}
		else
		{
			errorMessage(exp) << ptr->type() << "::" << exp->name << " is not declared.";
			boss->emit(Signal_Message, message);
			script_member(script)->sourceMessage(message);
			return 0;
		}
	}
	return ptr;
}
bool member_BSource::checkPath(BExpHolderArray& exps)
{
	for (int i = 0; i < exps.size(); i++)
	{
		BExp* exp = exps[i];
		if (exp->syntax == Syntax_Opera && exp->name == '.')
			exps.remove(i--);
	}
	return true;
}

bool IsPunct(char c)
{
	if(c == '_')
		return false;
	return ispunct(c);
}
int member_BSource::nextWord(BString& word, const BString& text, int& pos, int& line)
{
	char c = 0;
	while (pos < text.size())
	{
		c = text[pos];
		if (c == '\n')
			line++;
		if (!isspace(c))
			break;
		pos++;
	}
	if (pos == text.size())
	{
		word.reset();
		return text.size();
	}
	int begin = pos;
	if (c == ':' && text[pos + 1] == ':')
	{
		word = "::";
		pos += 2;
		return begin;
	}
	if (c == '/' && text[pos + 1] == '*')
	{
		word = "/*";
		pos += 2;
		return begin;
	}
	if (c == '/' && text[pos + 1] == '/')
	{
		word = "//";
		pos += 2;
		return begin;
	}
	if (c == '\"')
	{
		int begin = pos++;
		pos = text.find('\"', pos);
		word.reset(text, begin, ++pos);
		return begin;
	}
	if (c == '.' || c == ',' || c == ';' || c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}')
	{
		word = c;
		pos += 1;
		return begin;
	}
	if (c == '+' && text[pos + 1] == '+')
	{
		word = "++";
		pos += 2;
		return begin;
	}
	if (c == '-' && text[pos + 1] == '-')
	{
		word = "--";
		pos += 2;
		return begin;
	}
	if (c == '-' && text[pos + 1] == '>')
	{
		word = "->";
		pos += 2;
		return begin;
	}
	if (c == '<' || c == '>' || c == '!' || c == '+' || c == '-' || c == '*' || c == '/' || c == '|')
	{
		word = c;
		if (text[pos + 1] == '=')
		{
			word << '=';
			pos += 2;
			return begin;
		}
		pos++;
		return begin;
	}
	if (isdigit(text[pos]))
	{
		int end = pos;
		while (++end < text.size())
		{
			if (text[end] == '.' && !isdigit(text[end + 1]))
				break;
			if (!isdigit(text[end]))
				break;
		}
		word.reset(text, begin, end);
		pos = end;
		return begin;
	}
	if (IsPunct(text[pos]))
	{
		int end = pos;
		while (end < text.size())
		{
			if (isspace(text[end]))
				break;
			if (!IsPunct(text[end]))
				break;
			end++;
		}
		word.reset(text, begin, end);
		pos = end;
		return begin;
	}
	while (pos < text.size())
	{
		if (isspace(text[pos]))
			break;
		if (IsPunct(text[pos]))
			break;
		pos++;
	}
	word.reset(text, begin, pos);
	return begin;
}
int member_BSource::findSplit(BExpHolderArray& exps)
{
	for (int i = 0; i < exps.size(); i++)
	{
		BExp* exp = exps[i];
		if (exp->syntax == Syntax_Opera && exp->name == ',')
			return i;
	}
	return exps.size();
}
BString member_BSource::funcName(BExp* exp)
{
	BString funcName;
	if (exp->syntax != Syntax_Decl)
	{
		funcName = exp->name;
	}
	funcName << '(';
	for (int i = 0; i < exp->params.size(); i++)
	{
		funcName << exp->params[i]->type << ',';
	}
	funcName -= ',';
	funcName << ')';
	return funcName;
}
BClass* member_BSource::findClass(const BString& type)
{
	if (BClass* cls = member_BScript::basicClassMap(type))
		return cls;
	if (BClass* cls = script_member(script)->presets.classMap(type))
		return cls;
	if (BClass* cls = classMap(type))
		return cls;
	return 0;
}
Function* member_BSource::findFunction(const BString& name)
{
	if (Function* func = script_member(script)->presets.functionMap(name))
		return func;
	if (Function* func = functionMap(name))
		return func;
	return 0;
}
bool member_BSource::matchFunction(BExp* exp, Function* function)
{
	BExpHolderArray params = exp->params;
	for (int i = 0; i < exp->params.size(); i++)
	{
		const BString& type = function->params[i].type();
		if (type == exp->params[i]->type)
			continue;
		BClass* cls = findClass(type);
		if (cls == 0)
			continue;
		BExp* param = exp->params[i];
		BExp* decl = new BExp(Syntax_Decl);
		decl->type = type;
		decl->info = param->info;
		decl->params.reset();
		decl->params.append(param);
		if (!checkExp(decl))
			return false;
		params[i] = decl;
	}
	exp->params = params;
	exp->name = funcName(exp);
	exp->value = function;
	return true;
}
bool member_BSource::matchMethod(BExp* exp, Method* method)
{
	BExpHolderArray params = exp->params;
	for (int i = 0; i < exp->params.size(); i++)
	{
		const BString& type = method->params[i].type();
		if (type == exp->params[i]->type)
			continue;
		BClass* cls = findClass(type);
		if (cls == 0)
			continue;
		BExp* param = exp->params[i];
		BExp* decl = new BExp(Syntax_Decl);
		decl->type = type;
		decl->info = param->info;
		decl->params.append(param);
		if (!checkExp(decl))
			return false;
		params[i] = decl;
	}
	exp->params = params;
	return true;
}
